package star.oath.framework.util;

import java.lang.reflect.Array;
import java.math.*;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class CollectionUtils {

    /**
     * 判断集合是否为空（null或size为0）
     * @param collection 待检查的集合
     * @return 如果集合为null或空，返回true；否则返回false
     */
    public static boolean isEmpty(Collection<?> collection) {
        return collection == null || collection.isEmpty();
    }

    /**
     * 判断集合是否不为空（既不是null也不是size为0）
     * @param collection 待检查的集合
     * @return 如果集合不为null且非空，返回true；否则返回false
     */
    public static boolean isNotEmpty(Collection<?> collection) {
        return !isEmpty(collection);
    }

    /**
     * 判断 Map 是否为空（null 或 size 为 0）
     * @param map 待检查的 Map
     * @return 如果 Map 为 null 或空，返回 true；否则返回 false
     */
    public static boolean isEmpty(Map map) {
        return map == null || map.isEmpty();
    }

    /**
     * 判断 Map 是否不为空（既不是 null 也不是 size 为 0）
     * @param map 待检查的 Map
     * @return 如果 Map 不为 null 且非空，返回 true；否则返回 false
     */
    public static boolean isNotEmpty(Map map) {
        return !isEmpty(map);
    }

    /**
     * 将List转换为数组
     * @param list 待转换的List
     * @param <T> 元素类型
     * @return 转换后的数组，如果list为null则返回null
     */
    @SuppressWarnings("unchecked")
    public static <T> T[] toArray(List<T> list) {
        if (list == null) {
            return null;
        }
        // 获取泛型的实际类型
        Class<?> componentType = list.getClass().getComponentType();
        if (componentType == null && !list.isEmpty()) {
            componentType = list.get(0).getClass();
        }
        // 使用反射创建正确类型的数组
        T[] array = (T[]) Array.newInstance(componentType, list.size());
        return list.toArray(array);
    }

    /**
     * 从List<Map>中提取两个字段作为键值对，构建新的Map
     * @param list 源列表
     * @param keyField 用作键的字段名
     * @param valueField 用作值的字段名
     * @param <K> 键的类型
     * @param <V> 值的类型
     * @return 包含键值对的新Map
     */
    public static <K, V> Map<K, V> extractToMap(List<Map<String, Object>> list, String keyField, String valueField) {
        Map<K, V> result = new HashMap<>();
        for (Map<String, Object> map : list) {
            if (map.containsKey(keyField) && map.containsKey(valueField)) {
                @SuppressWarnings("unchecked")
                K key = (K) map.get(keyField);
                @SuppressWarnings("unchecked")
                V value = (V) map.get(valueField);
                result.put(key, value);
            }
        }
        return result;
    }

    /**
     * 从List<Map>中获取每个map指定key的所有数据，存入一个List后返回
     * @param list 源列表
     * @param key 指定的key
     * @param <T> 值的类型
     * @return 列表
     */
    public static <T> List<T> getValues(List<Map<String, Object>> list, String key) {
        List<T> values = new ArrayList<>();
        for (Map<String, Object> map : list) {
            if (map.containsKey(key)) {
                @SuppressWarnings("unchecked")
                T value = (T) map.get(key);
                values.add(value);
            }
        }
        return values;
    }

    /**
     * 从List<Map>中获取每个map指定key的所有去重数据，存入一个List后返回
     * @param list 源列表
     * @param key 指定的key
     * @param <T> 值的类型
     * @return 包含去重值的列表
     */
    public static <T> List<T> getDistinctValues(List<Map<String, Object>> list, String key) {
        Set<T> distinctValues = new LinkedHashSet<>();
        for (Map<String, Object> map : list) {
            if (map.containsKey(key)) {
                @SuppressWarnings("unchecked")
                T value = (T) map.get(key);
                distinctValues.add(value);
            }
        }
        return new ArrayList<>(distinctValues);
    }

    /**
     * 将List<Map>的每一个map按照某一个key转化为Map<key, map>
     * @param list 源列表
     * @param keyField 用作Map键的字段名
     * @param <K> 键的类型
     * @return 转换后的Map
     * @throws IllegalArgumentException 如果存在重复的键值
     */
    public static <K> Map<K, Map<String, Object>> toMapByKey(List<Map<String, Object>> list, String keyField) {
        Map<K, Map<String, Object>> result = new HashMap<>();
        for (Map<String, Object> map : list) {
            if (!map.containsKey(keyField)) {
                throw new IllegalArgumentException("Map missing key: " + keyField);
            }
            @SuppressWarnings("unchecked")
            K key = (K) map.get(keyField);
            if (result.containsKey(key)) {
                throw new IllegalArgumentException("Duplicate key value found: " + key);
            }
            result.put(key, map);
        }
        return result;
    }

    /**
     * 将List<Map>的每一个map按照某一个key转化为Map<key, List<map>>，允许重复键
     * @param list 源列表
     * @param keyField 用作Map键的字段名
     * @param <K> 键的类型
     * @return 转换后的Map
     */
    public static <K> Map<K, List<Map<String, Object>>> toMapListByKey(List<Map<String, Object>> list, String keyField) {
        Map<K, List<Map<String, Object>>> result = new HashMap<>();
        for (Map<String, Object> map : list) {
            if (!map.containsKey(keyField)) {
                continue; // 跳过不包含指定key的map
            }
            @SuppressWarnings("unchecked")
            K key = (K) map.get(keyField);
            result.computeIfAbsent(key, k -> new ArrayList<>()).add(map);
        }
        return result;
    }

    /**
     * 按数字键对Map列表进行正序排序
     * @param targetList 待排序的Map列表
     * @param mapKey 用于排序的键
     * @param <T> 键对应值的类型
     * @return 排序后的新列表
     */
    public static <T> List<Map<String, T>> sortByKeyAscending(List<Map<String, T>> targetList, String mapKey) {
        List<Map<String, T>> sortedList = new ArrayList<>(targetList);
        sortedList.sort(Comparator.comparing(
                map -> new BigDecimal(map.get(mapKey).toString())
        ));
        return sortedList;
    }

    /**
     * 按数字键对Map列表进行倒序排序
     * @param targetList 待排序的Map列表
     * @param mapKey 用于排序的键
     * @param <T> 键对应值的类型
     * @return 排序后的新列表
     */
    public static <T> List<Map<String, T>> sortByKeyDescending(List<Map<String, T>> targetList, String mapKey) {
        List<Map<String, T>> sortedList = new ArrayList<>(targetList);
        sortedList.sort(Comparator.comparing(
                map -> new BigDecimal(map.get(mapKey).toString()),
                Comparator.reverseOrder()
        ));
        return sortedList;
    }

    /**
     * 按多个键对List<Map>进行升序排序，所有值按字符串处理
     * @param list 待排序的列表
     * @param keys 排序键，按传入顺序优先级递减
     * @return 排序后的新列表
     */
    public static List<Map<String, Object>> sortByKeysAscending(List<Map<String, Object>> list, String... keys) {
        return sortByKeysAsString(list, true, keys);
    }

    /**
     * 按多个键对List<Map>进行降序排序，所有值按字符串处理
     * @param list 待排序的列表
     * @param keys 排序键，按传入顺序优先级递减
     * @return 排序后的新列表
     */
    public static List<Map<String, Object>> sortByKeysDescending(List<Map<String, Object>> list, String... keys) {
        return sortByKeysAsString(list, false, keys);
    }

    /**
     * 按多个键对List<Map>进行排序，所有值按字符串处理（内部实现）
     * @param list 待排序的列表
     * @param ascending 是否升序
     * @param keys 排序键，按传入顺序优先级递减
     * @return 排序后的新列表
     */
    private static List<Map<String, Object>> sortByKeysAsString(List<Map<String, Object>> list, boolean ascending, String... keys) {
        if (list == null || list.isEmpty() || keys == null || keys.length == 0) {
            return new ArrayList<>(list);
        }
        List<Map<String, Object>> sortedList = new ArrayList<>(list);
        Comparator<Map<String, Object>> comparator = null;
        for (String key : keys) {
            Comparator<Map<String, Object>> keyComparator = (m1, m2) -> {
                Object v1 = m1.get(key);
                Object v2 = m2.get(key);
                String s1 = v1 != null ? v1.toString() : "";
                String s2 = v2 != null ? v2.toString() : "";
                return ascending ? s1.compareTo(s2) : s2.compareTo(s1);
            };
            if (comparator == null) {
                comparator = keyComparator;
            }
            else {
                comparator = comparator.thenComparing(keyComparator);
            }
        }
        sortedList.sort(comparator);
        return sortedList;
    }

    /**
     * 将列表元素顺序反转并返回新列表
     * @param list 原列表
     * @param <T> 元素类型
     * @return 反转后的新列表
     */
    public static <T> List<T> reverseList(List<T> list) {
        if (list == null) {
            return null;
        }
        List<T> reversed = new ArrayList<>(list);
        Collections.reverse(reversed);
        return reversed;
    }

    /**
     * 反转Map的key和value
     * @param map 原Map
     * @param <K> 原Map的键类型，反转后的值类型
     * @param <V> 原Map的值类型，反转后的键类型
     * @return 反转后的Map
     * @throws IllegalArgumentException 如果原Map中存在重复的值（反转后会导致键冲突）
     */
    public static <K, V> Map<V, K> reverseMap(Map<K, V> map) {
        Map<V, K> invertedMap = new HashMap<>();
        for (Map.Entry<K, V> entry : map.entrySet()) {
            if (invertedMap.containsKey(entry.getValue())) {
                throw new IllegalArgumentException("Duplicate value found: " + entry.getValue()
                        + ". Cannot invert to a Map with unique keys.");
            }
            invertedMap.put(entry.getValue(), entry.getKey());
        }
        return invertedMap;
    }

    /**
     * 反转Map的key和value，允许重复值（重复值对应的键会被收集到List中）
     * @param map 原Map
     * @param <K> 原Map的键类型，反转后的List元素类型
     * @param <V> 原Map的值类型，反转后的键类型
     * @return 反转后的Map（值为List类型）
     */
    public static <K, V> Map<V, List<K>> reverseMapWithListValues(Map<K, V> map) {
        Map<V, List<K>> invertedMap = new HashMap<>();
        for (Map.Entry<K, V> entry : map.entrySet()) {
            invertedMap.computeIfAbsent(entry.getValue(), k -> new ArrayList<>())
                    .add(entry.getKey());
        }
        return invertedMap;
    }

    /**
     * 返回集合中指定起始下标和截止下标的子集，超出部分用null填充
     * @param collection 源集合
     * @param startIndex 起始下标（包含）
     * @param endIndex 截止下标（不包含）
     * @param <T> 元素类型
     * @return 子集集合，如果源集合为null则返回null
     */
    public static <T> List<T> subCollection(Collection<T> collection, int startIndex, int endIndex) {
        if (collection == null) {
            return null;
        }
        if (startIndex < 0 || startIndex > endIndex) {
            throw new IllegalArgumentException(
                    String.format("Invalid indices: start=%d, end=%d (start must be non-negative and <= end)",
                            startIndex, endIndex));
        }
        List<T> result = new ArrayList<>(endIndex - startIndex + 1);
        List<T> list = new ArrayList<>(collection);
        int size = list.size();
        for (int i = startIndex; i <= endIndex; i++) {
            if (i < size) {
                result.add(list.get(i));
            } else {
                result.add(null);
            }
        }
        return result;
    }

    /**
     * 返回集合中指定起始下标和截止下标的子集，移除所有null元素
     * @param collection 源集合
     * @param startIndex 起始下标（包含）
     * @param endIndex 截止下标（包含）
     * @param <T> 元素类型
     * @return 子集集合，如果源集合为null则返回null
     */
    public static <T> List<T> subCollectionWithoutNull(Collection<T> collection, int startIndex, int endIndex) {
        List<T> subList = subCollection(collection, startIndex, endIndex);
        if (subList == null) {
            return null;
        }
        return subList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
    }

    /**
     * 移除List<Map>中每个Map的指定key
     * @param list 包含Map的列表
     * @param key 要移除的key集合
     * @return 修改后的列表引用
     */
    public static List<Map<String, Object>> removeKeyFromMapList(List<Map<String, Object>> list, String key) {
        if (list == null || key == null) {
            return list;
        }
        for (Map<String, Object> map : list) {
            if (map != null) {
                map.remove(key);
            }
        }
        return list;
    }

    /**
     * 移除List<Map>中每个Map的指定key
     * @param list 包含Map的列表
     * @param keys 要移除的key集合
     * @return 修改后的列表引用
     */
    public static List<Map<String, Object>> removeKeysFromMapList(List<Map<String, Object>> list, String... keys) {
        if (list == null || keys == null || keys.length == 0) {
            return list;
        }
        for (Map<String, Object> map : list) {
            if (map != null) {
                for (String key : keys) {
                    map.remove(key);
                }
            }
        }
        return list;
    }

    /**
     * 合并多个 List 为一个 List
     * @param lists 待合并的 List 数组
     * @param <T> 元素类型
     * @return 合并后的 List
     */
    @SafeVarargs
    public static <T> List<T> mergeLists(List<T>... lists) {
        List<T> result = new ArrayList<>();
        for (List<T> list : lists) {
            if (isNotEmpty(list)) {
                result.addAll(list);
            }
        }
        return result;
    }

    /**
     * 合并多个 Set 为一个 Set
     * @param sets 待合并的 Set 数组
     * @param <T> 元素类型
     * @return 合并后的 Set
     */
    @SafeVarargs
    public static <T> Set<T> mergeSets(Set<T>... sets) {
        Set<T> result = new HashSet<>();
        for (Set<T> set : sets) {
            if (isNotEmpty(set)) {
                result.addAll(set);
            }
        }
        return result;
    }

    /**
     * 根据条件过滤集合元素
     * @param collection 待过滤的集合
     * @param predicate 过滤条件
     * @param <T> 元素类型
     * @return 过滤后的集合
     */
    public static <T> List<T> filter(Collection<T> collection, Predicate<T> predicate) {
        if (isEmpty(collection)) {
            return new ArrayList<>();
        }
        return collection.stream()
                .filter(predicate)
                .collect(Collectors.toList());
    }

}
